package kamikaze.service;

import java.io.IOException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kamikaze.bean.HasKey;
import kamikaze.service.UserSession.Type;
import kamikaze.utils.Database;
import kamikaze.utils.Database.Template;
import kamikaze.utils.StringUtil;

public class LoginServlet extends HttpServlet {

	private static String USER_QUERY = "select u from User u where u.loginId =:loginId and u.password = :password";
	private static String ADMIN_QURY = "select u from Admin u where u.loginId =:loginId and u.password = :password";

	@Override
	protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException,
			IOException {

		// Database.get().
		final String type = req.getParameter("type");
		final String username = req.getParameter("username");
		String password = req.getParameter("password");

		final ErrorHandler errorHandler = new ErrorHandler();

		errorHandler.addErrorMessageIfNotNull(
				StringUtil.ensureMatch(
						username,
						StringUtil.PATTERN_ALPHANUMERIC,
						"username must be alphanumeric"));

		errorHandler.addErrorMessageIfNotNull(
				StringUtil.ensureNotBlank(password, "password"));

		if (errorHandler.handle(req, resp)) {
			return;
		}

		final String passwordHash = StringUtil.encrypt(password);

		if ("user".equals(type) || "admin".equals(type)) {

			final boolean isUser = "user".equals(type);

			Database.get().execute(new Template<Object>() {
				@Override
				public Object query(EntityManager em) throws Exception {
					@SuppressWarnings("unchecked")
					List<HasKey> list = em
							.createQuery(isUser ? USER_QUERY : ADMIN_QURY)
							.setParameter("loginId", username)
							.setParameter("password", passwordHash)
							.getResultList();

					if (list.isEmpty()) {
						errorHandler.addErrorMessageIfNotNull("login failure");
						return null;
					}

					UserSession.setTo(req, new UserSession(list.get(0).getKey(),
							isUser ? Type.User : Type.Admin));
					return null;
				}
			});

		}

		if (!errorHandler.handle(req, resp)) {
			resp.sendRedirect("/index");
		}
	}
}
